package com.xyauto.uilibx.colorpicker;

import android.content.Context;
import android.database.ContentObserver;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ComposeShader;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Looper;
import android.util.SparseArray;

import java.util.ArrayList;


public class BitmapColorHelper extends ContentObserver {


    private static BitmapColorHelper mInstance;
    private final SparseArray<CacheParams> mCacheMap;
    private final ArrayList<IBitmapColor> changeObservers;
    private final ArrayList<IBitmapColor> changeInstantlyObservers;
    private final Handler handler;


    private int[] colorArray;
    private IBitmapColorProvider colorProvider;
    private IBitmapLayerProvider layerProvider;

    private BitmapColorHelper() {
        super(new Handler());
        handler = new Handler(Looper.getMainLooper());
        changeObservers = new ArrayList<>();
        changeInstantlyObservers = new ArrayList<>();
        mCacheMap = new SparseArray<>();
        layerProvider = new DefaultLayerProvider();
    }

    public void setColorProvider(IBitmapColorProvider colorProvider) {
        this.colorProvider = colorProvider;
    }


    public void setLayerProvider(IBitmapLayerProvider layerProvider){
        if (layerProvider==null){
            throw new NullPointerException("layerProvider is null");
        }
        this.layerProvider = layerProvider;
    }


    public static BitmapColorHelper getInstance() {
        if (mInstance == null) {
            mInstance = new BitmapColorHelper();
        }
        return mInstance;
    }


    public static ColorParams findColour() {
        BitmapColorHelper colorUtils = getInstance();
        int[] colorArray = colorUtils.colorArray;
        if (colorArray == null) {
            colorArray = colorUtils.reloadColor();
        }
        return new ColorParams(colorArray);
    }


    public static SparseArray<CacheParams> getCacheMap() {
        return getInstance().mCacheMap;
    }

    public static Bitmap createBitmap(Bitmap bitmap, Shader shader) {
        if (bitmap == null) return null;
        if (shader == null) return bitmap;
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        Bitmap newBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        ComposeShader composeShader = new ComposeShader(bitmapShader, shader, PorterDuff.Mode.SRC_ATOP);
        Paint paint = new Paint();
        paint.setShader(composeShader);
        Canvas canvas = new Canvas(newBitmap);
        canvas.drawRect(0, 0, width, height, paint);
        return newBitmap;
    }

    public static int getGradientSize() {
        return getInstance().layerProvider.getGradientSize();
    }


    public static int getLayerSize() {
        return getInstance().layerProvider.getLayerSize();
    }

    /**
     * 获取layerIndex 可用于找到对应的layerColor
     *
     * @param layerId
     * @return layerIndex
     */

    public static int getLayerIndex(int layerId) {
        return getInstance().layerProvider.getLayerIndex(layerId);
    }

    public static void loadSkinLayerId(Context context) {
        getInstance().loadLayerId(context);
    }

    public Drawable loadResDrawable(Context context, int res) {
        return getInstance().loadTargetResDrawable(context,res);
    }


    public void registerContentObserver(IBitmapColor observer, boolean isInstantly) {
        if (observer == null) return;
        ArrayList<IBitmapColor> observers = isInstantly ? changeInstantlyObservers : changeObservers;
        if (!observers.contains(observer)) {
            observers.add(observer);
        }
    }

    public void unregisterContentObserver(IBitmapColor observer) {
        if (observer == null) return;
        if (!changeInstantlyObservers.remove(observer)) {
            changeObservers.remove(observer);
        }
    }


    private int[] reloadColor() {
        colorArray = new int[getGradientSize() * getLayerSize()];
        if (colorProvider != null) {
            colorProvider.reloadColor(colorArray, getGradientSize(), getLayerSize());
        } else {
            for (int i : colorArray) {
                colorArray[i] = Color.TRANSPARENT;
            }
        }
        return colorArray;
    }

    private void loadLayerId(Context context) {
        layerProvider.loadTargetResLayerId(context);
    }

    private Drawable loadTargetResDrawable(Context context, int res) {
        return layerProvider.loadTargetResDrawable(context,res);
    }


    @Override
    public void onChange(boolean selfChange) {
        super.onChange(selfChange);
        handler.post(instantlyObserversRun);
        handler.removeCallbacks(observersRun);
        handler.postDelayed(observersRun, 500);
    }

    private final Runnable observersRun = new Runnable() {
        @Override
        public void run() {
            ColorParams params = new ColorParams(reloadColor());
            for (IBitmapColor observer : changeObservers) {
                try {
                    observer.changeColor(params);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    };

    private final Runnable instantlyObserversRun = new Runnable() {
        @Override
        public void run() {
            ColorParams params = new ColorParams(reloadColor());
            for (IBitmapColor observer : changeInstantlyObservers) {
                try {
                    observer.changeColor(params);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    };
}
